#ifndef CAN_H
#define CAN_H

#include "ICANCmd.h"
#include "can/candevice.h"
#include "utility.h"
#include <QDebug>
#include <QObject>
#include <QThread>
#include <QTimer>
#include <param.h>

#define ZLGCAN  // UPDATE 选择can卡：  ZLGCAN NJLAKCAN

#ifdef NJLAKCAN
#include "can/njlikecandevice.h"
#define CAN_DEVICE_TYPE LCMiniPcie_432
#define CAN_DEVICE_RESULT_OK CAN_RESULT_OK
#define CAN_DEVICE_RESULT_ERROR CAN_RESULT_ERROR
#define CAN_NAME "NJLAK"
#endif

#ifdef ZLGCAN
#include "can/zlgcandevice.h"
#define CAN_DEVICE_TYPE VCI_USBCAN2
#define CAN_DEVICE_RESULT_OK STATUS_OK
#define CAN_DEVICE_RESULT_ERROR STATUS_ERR
#define CAN_NAME "ZLG"
#endif

/********** 舵轮驱动直行与转角CAN1口 **********/
class CAN : public QObject {
    Q_OBJECT
public:
    explicit CAN( QObject* parent = nullptr );
    bool CanOpenAndStart();                             // 打开can设备
    bool CanStopAndClose();                             // 关闭can设备
    bool CanRecviveData();                              //处理can接收的数据
    void CanSendData( CanDataFrame* frames, ULONG i );  //处理can发送的数据
    void RegularGetData();                              //定期获取can数据

    void CanDataFrameOperationalMode( CAN_DataFrame& frame, BYTE value );                      // 伺服电机设置操作模式
    void CanDataFrameSpeedMode( CAN_DataFrame& frame, BYTE drive_id );                         // 伺服电机设置速度模式
    void CanDataFrameHomeMode( CAN_DataFrame& frame, BYTE drive_id );                          // 伺服电机设置回零模式
    void CanDataFramePositionMode( CAN_DataFrame& frame, BYTE drive_id );                      // 伺服电机设置位置模式
    void CanDataFrameControlByte0F( CanDataFrame& frame, BYTE drive_id );                      // 伺服电机使能控制字0F
    void CanDataFrameControlByte1F( CAN_DataFrame& frame, BYTE drive_id );                     // 伺服电机使能控制字1F
    void CanDataFrameControlByte2F( CAN_DataFrame& frame, BYTE drive_id );                     // 伺服电机使能控制字2F
    void CanDataFrameControlByte3F( CanDataFrame& frame, BYTE drive_id );                      // 伺服电机使能控制字3F
    void CanDataFrameControlByte00( CAN_DataFrame& frame, BYTE drive_id );                     // 伺服电机使能控制字00
    void CanDataFrameControlByte06( CAN_DataFrame& frame, BYTE drive_id );                     // 伺服电机使能控制字06
    void CanDataFrameAcce( CAN_DataFrame& frame, BYTE drive_id, long value );                  // 伺服电机设置加速度
    void CanDataFrameDece( CAN_DataFrame& frame, BYTE drive_id, long value );                  // 伺服电机设置减速度
    void CanDataFrameSetSpeedValue( CAN_DataFrame& frame, BYTE drive_id, long value );         // 伺服电机设置速度值
    void CanDataFrameGetCurSpeedValue( CAN_DataFrame& frame, BYTE drive_id );                  // 伺服电机获取速度值
    void CanDataFrameGetCurPoseValue( CanDataFrame& frame, BYTE drive_id );                    // 伺服电机获取当前位置
    void CanDataFrameGetCurVoltage( CAN_DataFrame& frame, BYTE drive_id );                     // 伺服电机获取母线电压值
    void CanDataFrameSetPosModeSpeedValue( CAN_DataFrame& frame, BYTE drive_id, long value );  // 伺服电机设置位置模式下的速度值
    void CanDataFrameSetPoModePosValue( CanDataFrame& frame, BYTE drive_id, long value );      // 伺服电机设置位置模式下的位置值
    void CanDataFrameGetErrInfo( CAN_DataFrame& frame, BYTE drive_id );                        // 伺服电机获取故障代码
    void CanDataFrameNodeProtectTimer( CAN_DataFrame& frame, BYTE drive_id, long value );      //节点保护时间(单位:ms)
    void CanDataFrameNodeProtectFactor( CAN_DataFrame& frame, BYTE drive_id, long value );     //节点保护因子
    void CanDataFrameRemote( CAN_DataFrame& frame, BYTE drive_id );                            // 节点超时保护 远程帧

    void AccDecUpdate( double& acc, double& dec );
    bool SetLiftDrivePositionModePosValue( int value );  //设定位置
    bool SetTurnDrivePositionModePosValue( int value );  //设定位置
    // UPDATE 2022.07.11获取驱动的错误信息
    void GetDriveErrInfo();                              //获取驱动的错误信息
    void DealDriveErrInfo( QString str, int err_info );  //处理故障信息
    //外部调用
    void GetCanRecivNaviParam( double* walkspeed, double* veerad );  //外部获取实际信息
    void CanSetSpeedAngle( double walk_speed, double veer_rad );     //外部设定行走速度值, 转角弧度值
    //托盘叉车舵轮控制
    void CanDataFrameSetForkRaiseSpeed( CanDataFrame& frame, uchar value );                            //发送柯蒂斯升降速度-1232C
    void CanDataFrameSetKDSData( CanDataFrame& frame, short& speed, uchar& kdsRise, uchar& kdsFall );  //上升电磁阀速度 id222 0~255
    void ARES_init();
    //科迪斯控制器F2A
    void CanDataFrameSetForkContorl( CanDataFrame& frame, uchar& lift_enable, short& fork_lft_speed, short& kds_fall );  //发送柯蒂斯货叉升降控制-F2A
    void CanDataFrameSetKDSWalkData( CanDataFrame& frame, uchar& Direction_enable, short& speed, short& acc, short& dec, short& max_acc, short& max_dec,
                                     short& brake_strength );  //发送柯蒂斯行走速度-F2A

    //托盘叉车外部调用
    void push_fork_upper();  //上升
    void push_fork_stop();   //停止
    void push_fork_down();   //下降

    void forward_direction();   //前进方向
    void Backward_direction();  //后退方向
    void Stop_direction();      //停止

    DWORD dw_DeviceHandle;

private:
    DWORD dw_Index   = 0;     /* 第1个设备 */
    DWORD dw_Channel = 0;     /* 第1个通道 */
    BYTE  dw_Btr0    = 0x03;  // BTR0   0014 -1M 0016-800K 001C-500K 011C-250K 031C-125K 041C-100K 091C-50K 181C-20K 311C-10K BFFF-5K
    BYTE  dw_Btr1    = 0x1c;

    BYTE can_operation_enable                     = 0x01;  // 伺服can操作模式使能
    BYTE can_operation_disable                    = 0x02;  // 伺服can操作模式失能
    BYTE turn_drive_id                            = 0x02;
    BYTE home_mode[ 8 ]                           = { 0x2F, 0x60, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00 };  // 设置伺服回零模式
    BYTE position_mode[ 8 ]                       = { 0x2F, 0x60, 0x60, 0x00, 0x01, 0x00, 0x00, 0x00 };  // 设置伺服位置模式
    BYTE speed_mode[ 8 ]                          = { 0x2F, 0x60, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00 };  // 设置伺服速度模式
    BYTE enable_mode_0F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x0F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能0F--使能驱动器
    BYTE enable_mode_1F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x1F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能1F--启动回零
    BYTE enable_mode_2F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x2F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能2F
    BYTE enable_mode_3F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x3F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能3F
    BYTE disable_mode_00[ 8 ]                     = { 0x2B, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 设置伺服软件失能00
    BYTE disable_mode_06[ 8 ]                     = { 0x2B, 0x40, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00 };  // 设置伺服软件失能06
    BYTE set_zero_pos[ 8 ]                        = { 0x23, 0x40, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 编码器位置清零
    BYTE get_cur_speed[ 8 ]                       = { 0x40, 0x69, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取伺服速度
    BYTE get_cur_speed_2[ 8 ]                     = { 0x40, 0x6C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取伺服速度-步科驱动使用
    BYTE get_cur_pos[ 8 ]                         = { 0x40, 0x64, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取伺服位置
    BYTE get_cur_voltage[ 8 ]                     = { 0x40, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取电压值
    BYTE set_speed_value[ 4 ]                     = { 0x23, 0xFF, 0x60, 0x00 };                          // 设定速度模式下速度值
    BYTE set_drive_accec[ 4 ]                     = { 0x23, 0x83, 0x60, 0x00 };                          // 设定加速度
    BYTE set_drive_dece[ 4 ]                      = { 0x23, 0x84, 0x60, 0x00 };                          // 设定减速度
    BYTE set_drive_position_mode_speed_value[ 4 ] = { 0x23, 0x81, 0x60, 0x00 };                          // 设定位置模式下的速度值
    BYTE set_drive_position_mode_pos_value[ 4 ]   = { 0x23, 0x7A, 0x60, 0x00 };                          // 设定位置模式下的位置值
    BYTE get_current[ 8 ]                         = { 0x40, 0x1C, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取电流
    BYTE get_err_info[ 8 ]                        = { 0x40, 0x83, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取故障信息
    BYTE set_node_proetc_time[ 4 ]                = { 0x2B, 0x0C, 0x10, 0x00 };                          // 100C 是节点保护时间(单位:ms)
    BYTE set_node_proetc_factor[ 4 ]              = { 0x2F, 0x0D, 0x10, 0x00 };                          // 100D 是节点保护因子

    bool       is_open_can = false;  // can设备是否打开
    int        time        = 0;
    CanDevice* canDevice   = nullptr;
    //舵轮直行参数
    double fork_walk_setting_speed          = 0;                        //设定舵轮直行速度 m/s
    double fork_walk_reality_speed          = 0;                        // 舵轮反馈真实速度m/s
    double Walk_Wheel_R                     = 0.115;                    //舵轮直行半径 m
    double Walk_Wheel_C                     = 2 * M_PI * Walk_Wheel_R;  //舵轮周长 m
    double Walk_Wheel_Speed_Reduction_Radio = 27.84;                    //舵轮直行减速比
    //舵轮转角参数
    double   fork_veer_setting_rad            = 0;  // 设定舵轮转角 rad
    double   fork_veer_reality_rad            = 0;  //反馈真实舵轮转角 rad
    double   Veer_Wheel_Speed_Reduction_Radio = 0;  //舵轮转角减速比
    int      Zero_Pulse                       = 0;  //原点时脉冲数
    int      pulse_per                        = 0;  //电机一圈所需脉冲数值
    int      pos_mode_speed                   = 0;  // 位置模式下最大速度 rmp
    int      pos_mode_acc                     = 0;  //加速度 rps^2
    int      pos_mode_dec                     = 0;  //减速度 rps^2
    uint16_t ARES_status_word;                      //手自动切换状态字
    long     fork_calc_puls = 0;                    // ARES 脉冲值
    short    kds_speed      = 0;                    //行走速度

    BYTE Brake_strength   = 0;  //刹车强度
    BYTE Direction_enable = 0;  //方向使能

    BYTE kds_rise       = 0;  //上升控制字
    BYTE kds_fall       = 0;  //下降阀速度
    BYTE fork_lft_speed = 0;  //上升速度
    BYTE lifting_enable = 0;  //升级使能

signals:
    void sigSendTips( const QString& );
    void sigShowCanData( const QByteArray& tips, const QString& string );
    void sigLoseConnect( const QString& );

public slots:
    void sltCanInit();
    void sltTimeOut();
};

#endif  // CAN_H
